// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <lib/async/dispatcher.h>
#include <zircon/fidl.h>

__BEGIN_CDECLS

// A generic FIDL dispatch function.
//
// For FIDL interfaces with [Layout="Simple"], the C backend generates a
// dispatch function that decodes the |msg| and calls through an |ops| table.
//
// This function signature matches the structure of these generated functions
// but with the type of the |ops| table erased.
//
// Example:
//
//  fidl_bind(dispacher, channel, (fidl_dispatch_t*)spaceship_SpaceShip_dispatch, ctx, &kOps);
//
typedef zx_status_t(fidl_dispatch_t)(void* ctx, fidl_txn_t* txn,
                                     fidl_msg_t* msg, const void* ops);

// Binds a |dispatch| function to channel| using |dispatcher|.
//
// This function adds an |async_wait_t| to the given |dispatcher| that waits
// asynchronously for new messages to arrive on |channel|. When a message
// arrives, the |dispatch| function is called on one of the threads associated
// with the |dispatcher| with the |fidl_msg_t| as well as the given |ctx| and
// |ops|.
//
// Typically, the |dispatch| function is generated by the C backend for FIDL
// interfaces with with [Layout="Simple"] (see |fidl_dispatch_t|). These
// dispatch functions decode the |fidl_msg_t| and call through the |ops| table
// implementations of the interface's methods, passing along the |ctx| and a
// |fidl_txn_t| (if the method has a reply message).
//
// The |fidl_txn_t| passed to |dispatch| is valid only until |dispatch| returns.
// If the method has a reply message, the |reply| function on the |fidl_txn_t|
// object must be called synchronously within the |dispatch| call.
//
// Returns whether |fidl_bind| was able to begin waiting on the given |channel|.
// Upon any error, |channel| is closed and binding is terminated. Shutdown down
// the |dispatcher| also results in |channel| being closed.
zx_status_t fidl_bind(async_dispatcher_t* dispatcher, zx_handle_t channel,
                      fidl_dispatch_t* dispatch, void* ctx, const void* ops);

__END_CDECLS
